#pragma once

/*
 * 消息格式:
 * - REQUEST:  [Header 8B] + [Op 1B] + [Operand1 8B] + [Operand2 8B] = 25字节
 * - RESPONSE: [Header 8B] + [ErrorCode 1B] + [Result 8B] = 17字节
 * - ERROR:    [Header 8B] + [ErrorCode 1B] + [MsgLen 2B] + [Message 变长]
*/

#include <vector>
#include <string>

#include <stdlib.h>
#include <cstring>
#include <cstdint>
#include <cmath>

#include <arpa/inet.h>

namespace MathProtocol
{
    //<--- 全局变量 --->
    constexpr uint32_t kProtocolMagic = 0x4D415448; //魔数
    constexpr uint8_t kProtocolVersion = 1;         //版本
    constexpr uint16_t kDefaultPort = 8080;         //默认端口
    constexpr size_t kHeadSize = 8;                 //报头的大小
    constexpr size_t kErrorMessageMaxSize = 256;    //错误消息的最大大小

    //<--- 枚举 --->
    //消息类型
    enum class MessageType : uint8_t
    {
        REQUEST = 0x01,  //客户端请求消息
        RESPONSE = 0x02, //服务器回复消息
        ERROR = 0x03     //错误消息
    };
    //操作类型
    enum class Operation : uint8_t
    {
        ADD = 0x01,      //加法(+)
        SUBTRACT = 0x02, //减法(-)
        MULTIPLY = 0x03, //乘法(*)
        DIVIDE = 0x04    //除法(/)
    };
    //错误码
    enum class ErrorCode : uint8_t
    {
        SUCCESS = 0x00,              // 计算成功
        INVALID_OPERATION = 0x01,    // 无效的运算操作
        DIVISION_BY_ZERO  = 0x02,    // 除零错误
        INVALID_FORMAT    = 0x03,    // 消息格式错误
        PROTOCOL_ERROR    = 0x04,    // 协议错误
        OVERFLOW_ERROR    = 0x05     // 数值溢出错误
    };

    // 消息体长度常量
    constexpr uint16_t kRequestBodyLength = sizeof(Operation) + 2 * sizeof(double);  // 17字节
    constexpr uint16_t kResponseBodyLength = sizeof(ErrorCode) + sizeof(double);     // 9字节
    // 完整消息长度常量  
    constexpr size_t kRequestMessageLength = kHeadSize + kRequestBodyLength;      // 25字节
    constexpr size_t kResponseMessageLength = kHeadSize + kResponseBodyLength;    // 17字节

    //<--- 结构体 --->
    //消息报头(8byte)
    struct __attribute__((packed)) MessageHeader    //消息报头
    {                     
        uint32_t magic;   //魔术
        uint8_t version;  //版本号
        MessageType type; //消息类型
        uint16_t length;   //消息长度(不包含消息头)
    };
    //请求结构体(17byte)
    struct __attribute__((packed)) RequestMessage
    {
        Operation operation; //操作符
        double operand1;     //第一个操作数
        double operand2;      //第二个操作数
    };
    //回复信息结构体(9byte)
    struct __attribute__((packed)) ResponseMessage
    {
        ErrorCode errorCode;    //错误码
        double result;          //计算结果
    };
    //错误信息体(3byte)
    struct __attribute__((packed)) ErrorMessage
    {
        ErrorCode errorCode;    //错误信息
        uint16_t messageLength;  //错误消息长度
    };

    //<--- 协助函数 --->

    // 64位字节序转换兼容性处理
    #ifndef htobe64
    inline uint64_t htobe64_compat(uint64_t host_64bits) {
        return htonl(1) == 1 ? host_64bits : __builtin_bswap64(host_64bits);
    }
    inline uint64_t be64toh_compat(uint64_t big_endian_64bits) {
        return ntohl(1) == 1 ? big_endian_64bits : __builtin_bswap64(big_endian_64bits);
    }
    #define htobe64 htobe64_compat
    #define be64toh be64toh_compat
    #endif

    inline void putU16Be(uint16_t value, uint8_t* ptr){
        uint16_t bevalue = htons(value);
        std::memcpy(ptr, &bevalue, sizeof(uint16_t));
    }

    inline void putU32Be(uint32_t value, uint8_t* ptr){
        uint32_t bevalue = htonl(value);
        std::memcpy(ptr, &bevalue, sizeof(uint32_t));
    }

    inline void putU64Be(uint64_t value, uint8_t* ptr){
        uint64_t bevalue = htobe64(value);
        std::memcpy(ptr, &bevalue, sizeof(uint64_t));
    }

    inline void putF64Be(double value, uint8_t* ptr){
        uint64_t bits;
        std::memcpy(&bits, &value, sizeof(uint64_t));
        putU64Be(bits, ptr);
    }

    inline uint16_t getU16Be(const uint8_t* ptr){
        uint16_t value;
        std::memcpy(&value, ptr, sizeof(uint16_t));
        return ntohs(value);
    }

    inline uint32_t getU32Be(const uint8_t* ptr){
        uint32_t value;
        std::memcpy(&value, ptr, sizeof(uint32_t));
        return ntohl(value);
    }

    inline uint64_t getU64Be(const uint8_t* ptr){
        uint64_t value;
        std::memcpy(&value, ptr, sizeof(uint64_t));
        return be64toh(value);
    }

    inline double getF64Be(const uint8_t* ptr){
        uint64_t bits = getU64Be(ptr);
        double value;
        std::memcpy(&value, &bits, sizeof(uint64_t));
        return value;
    }


    //<--- 协议函数 --->
    std::vector<uint8_t> CreateRequest(Operation op, double operand1, double operand2){
        //创建消息报文数组
        std::vector<uint8_t> protocolRequest(kRequestMessageLength);
        uint8_t* ptr = protocolRequest.data();
        
        //序列化报头
        putU32Be(kProtocolMagic, ptr);                          //魔数转化字节序
        ptr += 4;
        *ptr++ = kProtocolVersion;                              //版本号
        *ptr++ = static_cast<uint8_t>(MessageType::REQUEST);    //消息类型
        putU16Be(kRequestBodyLength, ptr);
        ptr += 2;                                               //Request消息体长度
        
        //序列化消息体
        *ptr++ = static_cast<uint8_t>(op);                      //放入操作符
        putF64Be(operand1, ptr);                                //放入第一个操作数
        ptr += 8;
        putF64Be(operand2, ptr);                                //放入第二个操作数

        return protocolRequest;
    }

    //创建相应消息
    std::vector<uint8_t> CreateResponse(ErrorCode errorCode, double result){
        //创建消息报文数组
        std::vector<uint8_t> protocolResponse(kResponseMessageLength);
        uint8_t* ptr = protocolResponse.data();
        
        //序列化报头
        putU32Be(kProtocolMagic, ptr);                          //魔数转化字节序
        ptr += 4;
        *ptr++ = kProtocolVersion;                              //版本号
        *ptr++ = static_cast<uint8_t>(MessageType::RESPONSE);    //消息类型
        putU16Be(kResponseBodyLength, ptr);
        ptr += 2;                                               //Request消息体长度

        //序列化消息体
        *ptr++ = static_cast<uint8_t>(errorCode);               //放入相应码
        putF64Be(result, ptr);                                  //放入结果

        return protocolResponse;
    }

    //创建错误消息
    std::vector<uint8_t> CreateError(ErrorCode errorCode, const std::string& message){
        //计算消息的长度
        size_t messageLength = std::min(kErrorMessageMaxSize, static_cast<size_t>(message.size()));
        
        //消息的有效
        size_t  bodyLength = sizeof(ErrorCode) + sizeof(uint16_t) + messageLength;

        //创建错误消息
        std::vector<uint8_t> protocolError(kHeadSize + bodyLength);
        uint8_t* ptr = protocolError.data();

        //序列化消息头
        putU32Be(kProtocolMagic, ptr);
        ptr += 4;
        *ptr++ = kProtocolVersion;
        *ptr++ = static_cast<uint8_t>(MessageType::ERROR);
        putU16Be(bodyLength, ptr);
        ptr += 2;

        //序列化消息体
        *ptr++ = static_cast<uint8_t>(errorCode);
        putU16Be(messageLength, ptr);
        ptr += 2;
        memcpy(ptr, message.c_str(), messageLength);

        return protocolError;
    }

    //解析消息头
    bool ParseHeader(const uint8_t* data, size_t size, MessageHeader& header){
        if(size < kHeadSize){//大小根本没有报头大
            return false;
        }

        const uint8_t* ptr = data;
        
        //解析消息头各段文字
        header.magic = getU32Be(ptr);                       //魔数
        ptr += 4;
        header.version = *ptr++;                            //版本
        header.type = static_cast<MessageType>(*ptr++);     //数据类型
        header.length = getU16Be(ptr);
        
        return (header.magic == kProtocolMagic && header.version == kProtocolVersion);
    }
    
    //解析RequestMessage消息
    bool ParseRequest(const uint8_t* data, size_t size, RequestMessage& request){
        if(size < kRequestMessageLength){
            return false;
        }

        const uint8_t* ptr = data + kHeadSize;//跳过消息头解析消息体
        
        request.operation = static_cast<Operation>(*ptr++);
        request.operand1 = getF64Be(ptr);
        ptr += 8;
        request.operand2 = getF64Be(ptr);

        return true;
    }

    //解析ResponseMessage消息
    bool ParseResponse(const uint8_t* data, size_t size, ResponseMessage& response){
        if(size < kResponseMessageLength){
            return false;
        }

        const uint8_t* ptr = data + kHeadSize;//跳过报头

        response.errorCode = static_cast<ErrorCode>(*ptr++);
        response.result = static_cast<double>(getF64Be(ptr));

        return true;
    }

    //解析错误消息
    bool ParseError(const uint8_t* data, size_t size, ErrorMessage& error, std::string& message){
        size_t minSize = kHeadSize + sizeof(ErrorCode) + sizeof(uint16_t);
        if(size < minSize) return false;

        const uint8_t* ptr = data + kHeadSize;//跳过报头

        error.errorCode = static_cast<ErrorCode>(*ptr++);
        error.messageLength = (getU16Be(ptr));
        ptr += 2;
        
        //验证消息长度是否合理
        if(error.messageLength > kErrorMessageMaxSize || size < minSize + error.messageLength){
            return false;
        }

        //提取错误信息
        message.assign(reinterpret_cast<const char*>(ptr), error.messageLength);

        return true;
    }

    //验证消息是否正确合理
    bool validateMessage(const uint8_t* data, size_t size){
        //解析消息头
        MessageHeader header;
        if(!ParseHeader(data, size, header)){
            return false;
        }

        //消息长度是否匹配
        if(size < kHeadSize + header.length){
            return false;
        }

        //根据消息类型验证消息长度
        switch(header.type){
            //请求消息
            case MessageType::REQUEST:
                return header.length == kRequestBodyLength;
            break;
            //相应消息
            case MessageType::RESPONSE:
                return header.length == kResponseBodyLength;
            break;
            //错误消息
            case MessageType::ERROR:
                if(header.length < sizeof(ErrorCode) + sizeof(uint16_t)){
                    return false;
                }
                
                if(size > kHeadSize + sizeof(ErrorCode) + sizeof(uint16_t)){
                    uint16_t msgLen = getU16Be(data + kHeadSize + sizeof(ErrorCode));
                    if(msgLen <= kErrorMessageMaxSize && header.length == sizeof(ErrorCode) + sizeof(uint16_t) + msgLen)
                    {
                        return true;
                    }
                }

                return false;
            break;
            //其它消息
            default:
                return false;
        }
    }

    //运算函数
    std::pair<ErrorCode, double> ExecuteOperation(Operation op, double operand1, double operand2){
        double result = 0.0;

        switch(op){
            case Operation::ADD:
                result = operand1 + operand2;
            break;
                case Operation::SUBTRACT:
                result = operand1 - operand2;
            break;
                case Operation::MULTIPLY:
                result = operand1 * operand2;
            break;
                case Operation::DIVIDE:
                if(operand2 == 0){
                    return {ErrorCode::DIVISION_BY_ZERO, 0.0};
                }
                result = operand1 / operand2;
            break;
            default:
                return {ErrorCode::INVALID_OPERATION, 0.0};
        }

        //检测是否是有效数值
        if(!std::isfinite(result)){
            return {ErrorCode::OVERFLOW_ERROR, 0.0};
        }

        return {ErrorCode::SUCCESS, result};
    }

    //                  <--- 辅助函数 --->

    //获取操作类型的字符串表示
    std::string GetOperationName(Operation op) {
        switch (op) {
            case Operation::ADD:      return "+";
            case Operation::SUBTRACT: return "-";
            case Operation::MULTIPLY: return "×";
            case Operation::DIVIDE:   return "÷";
            default:                  return "UNKNOWN";
        }
    }

    //获取错误代码的描述字符串
    std::string GetErrorDescription(ErrorCode code) {
        switch (code) {
            case ErrorCode::SUCCESS:           return "Success";
            case ErrorCode::INVALID_OPERATION: return "Invalid operation";
            case ErrorCode::DIVISION_BY_ZERO:  return "Division by zero";
            case ErrorCode::INVALID_FORMAT:    return "Invalid message format";
            case ErrorCode::PROTOCOL_ERROR:    return "Protocol error";
            case ErrorCode::OVERFLOW_ERROR:    return "Numeric overflow or underflow";
            default:                           return "Unknown error";
        }
    }
};